const FUN = require('../comm/func');
const rCache = require('../model/redis_cache');
const DB = require('../model/model_data');
const dbHelp = require('../comm/db-helper');
const timLib = require('../comm/time-lib');
const dataCalc = require('../comm/data-calc');
const PMR = require('../utils/policyManger');

module.exports = class Rise_Alarm
{
  //将数据库选项缓存到redis
  //policy 来自数据库的记录，附加了user_auth user_level字段
  //opts 数据库json字段的解析对象
  //CacheCallback 存储执行函数
  static InitCache(policy,opts,CacheCallback)
  {
    let obj=PMR.baseParam(policy);//即将缓存到redis的参数

    //检查json选项
    if( parseInt(policy.record_limit)==0 ||
        parseInt(opts.fetch_period)==0 ||
        parseInt(opts.target_id)==0 ||
        parseInt(opts.period)==0 )
    {
      console.error('wrong rise-alarm params',policy.id);
      return false;
    }

    //校验策略是否属于自己
    let policyNode=rCache.N_Policy+':'+policy.master;
    rCache.get(policyNode,opts.target_id,'hwid').then((val)=>{
      if(policy.master!=val) PMR.disablePolicy(policy.id);//停止处理策略
    })

    //json options参数存储
    obj.record_limit = policy.record_limit;//数据库条数上限
    obj.target_id = opts.target_id;
    obj.fetch_period = Number(opts.fetch_period)*60;//采样单位为分钟
    obj.period = Number(opts.period)*60;//总时段单位为分钟
    //obj.cache_expire = obj.period+60;//数据缓存reids有效期
    obj.span = opts.span;//最大跨度
    obj.excep = opts.excep;//剔除值
    obj.group = opts.group;
    obj.gname = opts.gname;
    obj.msg = opts.msg;

    //目标数据源，只能处理dat_json，且只能处理寄存器记录
    obj.target_table='dat_json';
    if(policy.db) obj.target_table += '_'+policy.uid;

    //数据库处理
    dbHelp.createTab(obj.table,policy.uid);

    //缓存主站参数
    obj.hwid = policy.master;
    CacheCallback(policy.id,policy.master,obj);//记录到缓存

    //开启定时器
    PMR.setSecInter(obj.policy_id,obj.fetch_period);
  }//end InitCache

  //处理json数据
  // topic = {project,devType,func,devId}
  // dConf即InitCache中的obj
  // dataBuf即mq消息内容，buf对象
  static async DataIn(topic,dConf,dataBuf)
  {
    return;
  }

  //周期回调
  static SecInter(dConf,nowStamp)
  {
    //pcyLog('[%d] secInter timer',dConf.policy_id,timLib.NowStr());

    let start=nowStamp-Number(dConf.period)*1000;
    let end=nowStamp+1000;
    //pcyLog('[%d] find',dConf.policy_id,timLib.Stamp2Str(start),timLib.Stamp2Str(end));
    DB.findByDuration(dConf.uid,dConf.target_table,dConf.target_id,start,end).then((rcds)=>{
      if(rcds) this.RiseHandler(dConf,rcds);
    })
  }

  //处理数据库记录
  static RiseHandler(dConf,records)
  {
    let excep=dConf.excep.split(',');
    let maxObjs={};
    let minObjs={};

    records.some((one)=>{//读取每一条
      //pcyLog('rcd',one.id,timLib.Stamp2Str(one.stamp));
      let jsonObj=JSON.parse(one.json);//json转对象
      for(let reg in jsonObj)//读取每个寄存器
      {
        if(isNaN(parseInt(reg))) continue;//剔除ave，max和min
        if(excep.includes(jsonObj[reg].toString())) continue;//去掉剔除值
        if(!maxObjs[reg]) maxObjs[reg]=jsonObj[reg];//初始化
        if(!minObjs[reg]) minObjs[reg]=jsonObj[reg];//初始化

        if(jsonObj[reg]>maxObjs[reg]) maxObjs[reg]=jsonObj[reg];//存最大值
        if(jsonObj[reg]<minObjs[reg]) minObjs[reg]=jsonObj[reg];//存最小值
      }
    })//end some

    let alarmFlag=false;
    let alarmObjs={};//报警的点
    let alarmMaxSpan=0;
    let alarmMaxReg=0;
    for(let reg in maxObjs)
    {
      //pcyLog('[%d] reg %d, max %d, min %d, %d ?> %d',dConf.policy_id,reg,maxObjs[reg],minObjs[reg],maxObjs[reg]-minObjs[reg],parseInt(dConf.span));
      if(maxObjs[reg]-minObjs[reg] > parseInt(dConf.span))//跨度过大，报警
      {
        alarmFlag=true;
        alarmObjs[reg]=maxObjs[reg]-minObjs[reg];
        if(alarmObjs[reg]>alarmMaxSpan)
        {
          alarmMaxSpan=alarmObjs[reg];
          alarmMaxReg=reg;
        }
        //pcyLog('[%d]',reg,maxObjs[reg],minObjs[reg],maxObjs[reg]-minObjs[reg]);
      }//end if maxobjs -
    }

    if(alarmFlag) //发出报警消息
    {
      let msg=dConf.msg
      msg=msg.replace(/#max/g,alarmMaxSpan);
      msg=msg.replace(/#reg/g,alarmMaxReg);

      //获取寄存器对应的组名
      let group_s=[];
      let group_e=[];
      let group=dConf.group.split(',');//0-3,9-6
      let gName=dConf.gname.split(',');//第一组,第二组
      let gIdx=[];//存储对应的组索引号，方便寻找组名，寄存器范围等

      for(let gg of group)
      {
        gg=gg.split('-');
        group_s.push(parseInt(gg[0]));
        group_e.push(parseInt(gg[0])+parseInt(gg[1]));
      }

      for(let reg in alarmObjs)//轮询报警值
      {
        for(let i=0;i<group_s.length;i++)//在组列表里看看有没有此寄存器
        {
          if(parseInt(reg)>=group_s[i] && parseInt(reg)<group_e[i])//确定是这个组的
          {
            gIdx[reg]=i;
            break;
          }
        }
      }

      let list='';//拼接报警组列表
      for(let reg in alarmObjs)
      {
        if(list!='') list+=',';
        list+=gName[gIdx[reg]]+'['+(reg-group_s[gIdx[reg]]+1)+']>'+alarmObjs[reg];
      }

      //替换组名和列表
      msg=msg.replace(/#name/g,gIdx[alarmMaxReg]);
      msg=msg.replace(/#list/g,list);

      pcyLog('[%d][%d] rise-alram reg[%d]',dConf.policy_id,dConf.hwid,alarmMaxReg,timLib.NowStr());
      DB.addAlaramLog(dConf.uid, dConf.hwid, dConf.policy_id, alarmMaxReg, msg, timLib.NowStamp()).then((id)=>{
        PMR.alarmReport(id,dConf);
      })

      //删除数据库中冗余的前期数据
      dataCalc.dbRecordTidy(dConf.uid,dConf.table,dConf.policy_id,dConf.record_limit);
    }

  }//end funciton
}